package com.mazaiting.lab.controller;

import com.mazaiting.web.domain.base.BasePageQuery;
import com.mazaiting.web.auth.security.annotation.PrePermission;
import com.mazaiting.web.utils.HttpUtil;
import com.mazaiting.lab.domain.form.BucketForm;
import com.mazaiting.lab.domain.vo.BucketVO;
import com.mazaiting.lab.domain.vo.ObjectFileVO;
import com.mazaiting.lab.service.IMinioFileService;
import com.mazaiting.minio.domain.FileInfo;
import com.mazaiting.minio.domain.PolicyInfo;
import com.mazaiting.minio.ex.MinioException;
import com.mazaiting.minio.service.IMinioService;
import com.mazaiting.mybatisplus.domain.vo.BasePageVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * minio 控制器
 *
 * @author mazaiting
 * @create_time 2022/10/7 19:14
 */
@Slf4j
@RestController
@RequestMapping("lab/v1/minio")
@RequiredArgsConstructor
public class MinioController {

    private final IMinioService minioService;
    private final IMinioFileService minioFileService;

    /**
     * 列出所有的桶
     *
     * @param basePageQuery 查询参数
     * @return 分页数据
     */
    @PrePermission("lab:minio:bucket:query")
    @GetMapping("listBuckets")
    public BasePageVO<BucketVO> listBuckets(BasePageQuery basePageQuery) throws Exception {
        return minioFileService.listBuckets(basePageQuery);
    }

    /**
     * 创建一个桶
     *
     * @param bucketForm 存储桶表单
     */
    @PrePermission("lab:minio:bucket:add")
    @PostMapping(value = "/createBucket")
    public void createBucket(BucketForm bucketForm) throws MinioException {
        minioService.createBucket(bucketForm.getName());
    }

    /**
     * 删除一个桶
     *
     * @param bucketName 存储桶名称
     */
    @PrePermission("lab:minio:bucket:delete")
    @DeleteMapping(value = "/deleteBucket/{bucketName}")
    public void deleteBucket(@PathVariable String bucketName) throws MinioException {
        minioService.removeBucket(bucketName);
    }

    /**
     * 上传一个文件
     *
     * @return 文件路径
     */
    @PrePermission("lab:minio:bucket:upload")
    @PostMapping("/uploadFile")
    public Map<String, String> uploadFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam String bucketName,
                                          @RequestParam(required = false) String objectName) throws Exception {
        minioService.createBucket(bucketName);
        String data;
        if (objectName != null) {
            data = minioService.putObject(bucketName, objectName, multipartFile);
        } else {
            data = minioService.putObject(bucketName, multipartFile.getOriginalFilename(), multipartFile);
        }
        return Collections.singletonMap("url", data);
    }

    /**
     * 递归列出一个桶中的所有文件和目录
     *
     * @return 文件列表
     */
    @PrePermission("lab:minio:file:query")
    @GetMapping("/listFiles/{bucketName}")
    public List<FileInfo> listFiles(@PathVariable String bucketName) {
        return minioService.listFiles(bucketName);
    }

    /**
     * 下载一个文件
     *
     * @param objectFileVO 对象文件 VO
     */
    @PrePermission("lab:minio:file:download")
    @GetMapping("/download")
    public void download(ObjectFileVO objectFileVO, HttpServletResponse response) throws Exception {
        // 对象名
        String objectName = objectFileVO.getObjectName();
        InputStream is = minioService.getObject(objectFileVO.getBucketName(), objectName);
        HttpUtil.download(response, is, objectName);
    }

    /**
     * 删除一个文件
     * @param bucketName 存储桶名
     * @param objectName 对象名
     */
    @PrePermission("lab:minio:file:delete")
    @DeleteMapping(value = "/deleteFile")
    public void deleteFile(@RequestParam String bucketName, @RequestParam String objectName) throws Exception {
        minioService.removeObject(bucketName, objectName);
    }

    /**
     * 获取临时授权-用于上传文件
     * h5 请求参数:
     * file: <文件>
     * x-amz-algorithm: "AWS4-HMAC-SHA256"
     * x-amz-credential: "admin/20221007/us-east-1/s3/aws4_request"
     * key: "文件名"
     * x-amz-signature: "836c571bfbcb9df0bce00f0fa14a60aea6f3884c9174f9cbe42fd49d852516ad"
     * x-amz-date: "20221007T155728Z"
     * policy: "eyJleHBpcmF0aW9uIjoiMjAyMi0xMC0wN1QxNjowNzoyOC40NjJaIiwiY29uZGl0aW9ucyI6W1siZXEiLCIkYnVja2V0IiwidGVzdCJdLFsiZXEiLCIka2V5IiwiNzEyNjA4NmYzOTY2MjI4ODUyZTY3NjA1ZDcwMjQyNWQuanBlZyJdLFsiZXEiLCIkeC1hbXotYWxnb3JpdGhtIiwiQVdTNC1ITUFDLVNIQTI1NiJdLFsiZXEiLCIkeC1hbXotY3JlZGVudGlhbCIsImFkbWluLzIwMjIxMDA3L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QiXSxbImVxIiwiJHgtYW16LWRhdGUiLCIyMDIyMTAwN1QxNTU3MjhaIl1dfQ=="
     *
     * @param objectFileVO 临时授权 VO
     * @return 协议参数
     */
    @PrePermission("lab:minio:policy")
    @GetMapping("policy")
    public PolicyInfo policy(ObjectFileVO objectFileVO) throws MinioException {
        return minioService.policy(objectFileVO.getBucketName(), objectFileVO.getObjectName());
    }

}
